package pos;

import com.sun.j3d.utils.behaviors.vp.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import pos.MainMenu.MainMenuController;
import pos.MessageBox.*;
import pos.utils.*;

/**
 * 系统的入口与控制中心，维护GUI窗口、全局设置，负责不同模式间的装卸和切换，初始化3D绘图环境
 * @author plus
 */
public class ControlCenter {
    private static GUIEntrance MyGUI;                      //图形界面的入口8
    private static IModeController CurrentMode;            //当前模式控制器
    private static Profile CurrentProfile;                 //全局配置变量
    
    private static PlatformGeometry dashBoard;
    public static TransformGroup dashBoardTG;       //面板根变形组
    public static OrderedGroup dashBoardRoot;       //面板根组
    public static BranchGroup objRoot;                  //实体根组
    
    public static OrbitBehavior orbit=new OrbitBehavior();
    
    public static PreFrameInvoker preFrameInvoker;      //逐帧调用器
    public static EventBehavior eventBehavior;          //输入事件触发器
    
    private static SimpleUniverse universe;
    static Canvas3D canvas;

    /**
     * 构造函数，从XML文件中装载持久性全局设置，并根据设置初始化GUI窗口(包括分辨率和是否全屏)、启动3D绘图环境
     */
    public ControlCenter() {
        CurrentProfile=new Profile();
        MyGUI = new GUIEntrance(CurrentProfile);
        initJ3D();
        
        setCurrentMode(new MainMenuController());
        
        MyGUI.add(canvas);
        canvas.setSize(MyGUI.width, MyGUI.height);
        MyGUI.transferFocus();
    }
    /**
     * 设置当前模式控制器。
     * 首先调用原模式控制器的终止方法，而后将新的模式控制器设置为新的当前控制器，最后调用新的当前控制器的启动方法
     * @param CurrentMode 需要启用的新的模式控制器
     */
    public static void setCurrentMode(IModeController NewMode) {
        if (CurrentMode!=null) CurrentMode.disposeMode();
        CurrentMode = NewMode;
        CurrentMode.setMode();
        
    }
    /**
     * 获得当前全局配置
     * @return 当前全局配置
     */
    public static Profile getCurrentProfile() {
        return CurrentProfile;
    }
    /**
     * 设置当前全局设置，并自动将新的全局设置应用到系统中，同时保存新的全局设置到XML文件
     * @param CurrentProfile 新的全局设置
     */
    public static void setCurrentProfile(Profile NewProfile) {
        CurrentProfile =new Profile(NewProfile);
        MyGUI.ChangeDisplayMode(CurrentProfile.getMode());
        resetDisplayScale();
    }
    
    
    private static void resetDisplayScale(){
        double YScale;
        YScale=((double)CurrentProfile.getMode().getHeight()/(double)CurrentProfile.getMode().getWidth())/0.75;
        Transform3D t3dYScale=new Transform3D();
        t3dYScale.setScale(new Vector3d(1,YScale,1));
        dashBoardTG.setTransform(t3dYScale);
    }
    
    private void initJ3D() {
        canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
        canvas.setStereoEnable(false);
        universe = new SimpleUniverse(canvas);
        
        objRoot = new BranchGroup();
        objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
        objRoot.setCapability(Group.ALLOW_CHILDREN_WRITE);
        objRoot.setCapability(BranchGroup.ALLOW_DETACH);
        
        preFrameInvoker=new PreFrameInvoker();
        objRoot.addChild(preFrameInvoker);
        
        eventBehavior=new EventBehavior(null,null);
        objRoot.addChild(eventBehavior);
        
        dashBoard = new PlatformGeometry();
        dashBoardTG=new TransformGroup();
        dashBoardRoot=new OrderedGroup();
        
        dashBoard.setCapability(PlatformGeometry.ALLOW_DETACH);
        
        dashBoardTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        dashBoardTG.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
        dashBoardTG.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);

        dashBoardRoot.setChildIndexOrder(null);
        dashBoardRoot.setCapability(OrderedGroup.ALLOW_CHILDREN_EXTEND);
        dashBoardRoot.setCapability(OrderedGroup.ALLOW_CHILDREN_WRITE);
        
        dashBoard.addChild(dashBoardTG);
        dashBoardTG.addChild(dashBoardRoot);
        
        resetDisplayScale();
        
        initLight();
        initView();
        
        objRoot.compile();
        dashBoard.compile();
        
        universe.addBranchGraph(objRoot);
        universe.getViewingPlatform().setPlatformGeometry(dashBoard);
        
    }
    
    private void initLight() {
        AmbientLight ALight = new AmbientLight(true, new Color3f(0.4f, 0.4f, 0.4f));
            ALight.setInfluencingBounds(new BoundingSphere(new Point3d(0d, 0d, 0d), 15000));
            
        Light Dlight = new PointLight(true, new Color3f(.7f, .7f, .7f),
                new Point3f(-200f, 800f, -200f), new Point3f(1f, 0, 0));
        Dlight.setInfluencingBounds(new BoundingSphere(new Point3d(0d, 0d, 0d), 10000));
        
        Light Dlight2 = new PointLight(true, new Color3f(0.25f, 0.25f, 0.25f),
                new Point3f(800f, 5f, 800f), new Point3f(1f, 0, 0));
        Dlight2.setInfluencingBounds(new BoundingSphere(new Point3d(0d, 0d, 0d), 15000));
        
        objRoot.addChild(ALight);
        objRoot.addChild(Dlight);
        objRoot.addChild(Dlight2);
    }
    /**
     * 设置当前3D视角的静态方法
     * @param pos 视角位置
     * @param rot 视角角度
     */
    public static void setView(Vector3d pos, Vector3d rot){
        Transform3D t3d = new Transform3D(), t3drx = new Transform3D(),
                    t3dry = new Transform3D(),t3drz = new Transform3D();
        t3d.set(pos);
        t3drx.rotX(rot.x);
        t3dry.rotY(rot.y);
        t3drz.rotZ(rot.z);
        t3drx.mul(t3dry);
        t3drx.mul(t3drz);
        t3d.mul(t3drx);
        
        universe.getViewingPlatform().getViewPlatformTransform().setTransform(t3d);
    }
    
    public static void showMessageBox(MessageBox box){
        MessageBoxController msgCtrl=new MessageBoxController(CurrentMode);
        msgCtrl.showMessageBox(box);
    }
    
    private void initView() {
        universe.getViewer().getView().setBackClipDistance(1500.0);
        universe.getViewer().getView().setFrontClipDistance(0.001);
        //universe.getViewer().getView().setTransparencySortingPolicy(View.TRANSPARENCY_SORT_GEOMETRY);
        //orbit.setSchedulingBounds(new BoundingSphere(new Point3d(),1000));
        //universe.getViewingPlatform().setViewPlatformBehavior(orbit);
    }
    
    public static void main(String args[]){                                     //应用程序入口
        new ControlCenter();
    }
}
